/*
    James McQueen, Tyson Nottingham, Michael Pogson
    TCSS 372 Winter 2012
    SC2 Simulator
    
    debug.h
*/

#ifndef DEBUG_H
#define DEBUG_H
#include "sc2sim.h"
#include "cpu.h"

#define DEFAULT_OBUF_SIZE 1024

#define MAX_BREAK_POINTS 16
#define MAX_INPUT_LEN 32
#define WORDS_PER_PAGE 16

#define LOAD 1
#define STEP 2
#define RUN 3
#define SET_REGISTER 4
#define MEMORY 5
#define QUIT 6
#define SET_PC 'P'
#define SET_SW 'S'

#define SET_MEMORY 1
#define SHOW_BREAKPOINTS 2
#define TOGGLE_BREAKPOINT 3
#define SCROLL_UP 4
#define SCROLL_DOWN 5

#define SP_REG_NUM 5
#define PC 0
#define IR 1
#define MAR 2
#define MDR 3
#define SW 4

#define CC_NUM 4
#define N_FLAG 5
#define Z_FLAG 6
#define C_FLAG 7
#define O_FLAG 8

char* mainMenuStr = "(1) Load   (2) Step   (3) Run   (4) Set Register   (5) Memory   (6) Quit";
char* registerMenuStr = "(0 - F) $Rx   (P) PC   (S) SW";
char* memoryMenuStr = "(1) Set Memory   (2) Show Breakpoints   (3) Toggle Breakpoint\n(4) Scroll Up   (5) Scroll Down";

char* spRegStrings[] = {
    "PC :",
    "IR :",
    "MAR:",
    "MDR:",
    "SW :",
    "N  :",
    "Z  :",
    "C  :",
    "O  :"
};

typedef struct {
    CPUPtr cpu;
    RegisterFilePtr rf;
    MemoryModulePtr mm;
    ushort breakPoints[MAX_BREAK_POINTS];
    ushort memDumpStart;
    ushort spRegValues[SP_REG_NUM + CC_NUM];
    char* oBuf;
    int oBufCapacity;
    int oBufPosition;
} DebugMonitor;

typedef DebugMonitor* DebugMonitorPtr;

DebugMonitorPtr debug_initialize(CPUPtr cpu);
void debug_clearBreakPoints(DebugMonitorPtr db);
void debug_start(DebugMonitorPtr db);
void debug_drawDataDisplay(DebugMonitorPtr db);
int debug_showMenu(DebugMonitorPtr db, char* options, int min, int max);
int debug_showRegisterMenu(DebugMonitorPtr db);
void debug_processMainMenu(DebugMonitorPtr db, int option);
void debug_processRegisterMenu(DebugMonitorPtr db, int option);
ushort debug_getData(DebugMonitorPtr db, char* prompt);
void debug_processMemoryMenu(DebugMonitorPtr db, int option);
void debug_setMemory(DebugMonitorPtr db);
void debug_showBreakPoints(DebugMonitorPtr db);
void debug_toggleBreakPointDialog(DebugMonitorPtr db);
void debug_toggleBreakPoint(DebugMonitorPtr db, ushort address);
void debug_load(DebugMonitorPtr db);
void debug_step(DebugMonitorPtr db);
void debug_run(DebugMonitorPtr db);
void debug_getSpRegValues(DebugMonitorPtr db);
int debug_isBreakPoint(DebugMonitorPtr db, ushort address);
void debug_clearMemory(DebugMonitorPtr db);
int debug_loadFile(DebugMonitorPtr db, char* file_name);
void debug_updateVideo(DebugMonitorPtr db);
void clearScreen();

#endif
